package com.gframework.mybatis.util.generator.gen;

import com.gframework.mybatis.util.generator.core.codegen.dom.xml.Attribute;
import com.gframework.mybatis.util.generator.core.codegen.dom.xml.TextElement;
import com.gframework.mybatis.util.generator.core.codegen.dom.xml.XmlElement;

/**
 * 扩展sql生成操作类可以继承此类，以简化某些操作.
 * 
 * @since 1.0.0
 * @author Ghwolf
 */
public abstract class AbstractGenerator {

	/**
	 * 取得一个特殊定制的mybatis mapper的where语句
	 * 
	 * @return 一个where Xml节点对象
	 */
	public XmlElement getSqlParamWhere() {
		XmlElement where = new XmlElement("where");
		
		XmlElement ifNotNull = new XmlElement("if");
		ifNotNull.addAttribute(new Attribute("test","paramList != null"));

		XmlElement outerForeach = new XmlElement("foreach");
		outerForeach.addAttribute(new Attribute("collection", "paramList"));
		outerForeach.addAttribute(new Attribute("item", "_sqlParam"));
		outerForeach.addElement(new TextElement("${_sqlParam.outerOp}"));
		
		XmlElement chooseAndOr = new XmlElement("choose");
		XmlElement whenOr = new XmlElement("when");
		XmlElement otherwiseAnd = new XmlElement("otherwise");
		whenOr.addAttribute(new Attribute("test","_sqlParam.innerOp == 'or'"));
		chooseAndOr.addElement(whenOr);
		chooseAndOr.addElement(otherwiseAnd);
		outerForeach.addElement(chooseAndOr);
		

		// innerForeach start
		XmlElement innerForeachAnd = new XmlElement("foreach");
		innerForeachAnd.addAttribute(new Attribute("collection", "_sqlParam.params"));
		innerForeachAnd.addAttribute(new Attribute("item", "_param"));
		innerForeachAnd.addAttribute(new Attribute("open", "("));
		innerForeachAnd.addAttribute(new Attribute("close", ")"));
		innerForeachAnd.addAttribute(new Attribute("separator", "and"));
		XmlElement innerForeachOr = new XmlElement("foreach");
		innerForeachOr.addAttribute(new Attribute("collection", "_sqlParam.params"));
		innerForeachOr.addAttribute(new Attribute("item", "_param"));
		innerForeachOr.addAttribute(new Attribute("open", "("));
		innerForeachOr.addAttribute(new Attribute("close", ")"));
		innerForeachOr.addAttribute(new Attribute("separator", "or"));

		XmlElement choose = new XmlElement("choose");
		innerForeachAnd.addElement(choose);
		innerForeachOr.addElement(choose);
		XmlElement when0 = new XmlElement("when");
		XmlElement when2 = new XmlElement("when");
		XmlElement when3 = new XmlElement("when");
		XmlElement otherwise = new XmlElement("otherwise");
		choose.addElement(when0);
		choose.addElement(when2);
		choose.addElement(when3);
		choose.addElement(otherwise);

		when0.addAttribute(new Attribute("test", "_param.type == 0"));
		when2.addAttribute(new Attribute("test", "_param.type == 2"));
		when3.addAttribute(new Attribute("test", "_param.type == 3"));

		when0.addElement(new TextElement("${_param.column} ${_param.operator}"));
		when2.addElement(new TextElement("${_param.column} ${_param.operator}"));
		XmlElement foreach = new XmlElement("foreach");
		foreach.addAttribute(new Attribute("collection", "_param.value"));
		foreach.addAttribute(new Attribute("item", "_item"));
		foreach.addAttribute(new Attribute("open", "("));
		foreach.addAttribute(new Attribute("close", ")"));
		foreach.addAttribute(new Attribute("separator", ","));
		foreach.addElement(new TextElement("#{_item}"));
		when2.addElement(foreach);

		when3.addElement(new TextElement("${_param.column} BETWEEN #{_param.value.begin} AND #{_param.value.end}"));

		otherwise.addElement(new TextElement("${_param.column} ${_param.operator} #{_param.value}"));
		whenOr.addElement(innerForeachOr);
		otherwiseAnd.addElement(innerForeachAnd);
		// innerForeach end

		ifNotNull.addElement(outerForeach);
		where.addElement(ifNotNull);
		return where;
	}
}
